{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Copyright (c) MONAI Consortium  \n",
    "Licensed under the Apache License, Version 2.0 (the \"License\");  \n",
    "you may not use this file except in compliance with the License.  \n",
    "You may obtain a copy of the License at  \n",
    "&nbsp;&nbsp;&nbsp;&nbsp;http://www.apache.org/licenses/LICENSE-2.0  \n",
    "Unless required by applicable law or agreed to in writing, software  \n",
    "distributed under the License is distributed on an \"AS IS\" BASIS,  \n",
    "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  \n",
    "See the License for the specific language governing permissions and  \n",
    "limitations under the License. \n",
    " \n",
    "# MONAI Label Hello, World! - Radiology App and Slicer Example\n",
    "\n",
    "***The Active Learning Process with MONAI Label***\n",
    "\n",
    "In this notebook, we provide a hello world example of MONAI Label use case. Using Spleen segmentation in Radiology app as the demonstration, 3D Slicer as the client viewer, we show how MONAI Label workflow serves as interacitve AI-Assisted tool for labeling CT scans. \n",
    "\n",
    "![workflow](./figures/monailabel_radiology_3dslicer/teaser_img.png)\n",
    "\n",
    "## 1. Prepare MONAI Label\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Setup environment\n",
    "\n",
    "### Prerequisites\n",
    "- **Install MONAI Label** weekly preview release: "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install monailabel"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1.1 Check Install and All Sample Apps"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Using PYTHONPATH=/home/chyang/anaconda3/envs:\n",
      "\n",
      "Available Apps are:\n",
      "----------------------------------------------------\n",
      "  endoscopy                     : /home/chyang/anaconda3/envs/monai/monailabel/sample-apps/endoscopy\n",
      "  monaibundle                   : /home/chyang/anaconda3/envs/monai/monailabel/sample-apps/monaibundle\n",
      "  pathology                     : /home/chyang/anaconda3/envs/monai/monailabel/sample-apps/pathology\n",
      "  radiology                     : /home/chyang/anaconda3/envs/monai/monailabel/sample-apps/radiology\n",
      "\n"
     ]
    }
   ],
   "source": [
    "!monailabel apps"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1.2 Download radiology app\n",
    "Choose \"radiology\" as the app"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Using PYTHONPATH=/home/chyang/anaconda3/envs:\n",
      "\n",
      "radiology is copied at: /home/chyang/Documents/monai_tutorials_gitee/monailabel/apps/radiology\n"
     ]
    }
   ],
   "source": [
    "!monailabel apps --download --name radiology --output apps"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1.3 Download sample data\n",
    "Download MSD Spleen dataset as the sample dataset using monailabel API. The task is the volumetric (3D) segmentation of the spleen from CT image. The segmentation of spleen is formulated as the voxel-wise 2-class classification. Each voxel is predicted as either foreground (spleen) or background. The dataset is from the 2018 MICCAI challenge.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Using PYTHONPATH=/home/chyang/anaconda3/envs:\n",
      "\n",
      "Task09_Spleen.tar: 1.50GB [04:20, 6.19MB/s]                                     \n",
      "2024-07-16 16:53:17,106 - INFO - Downloaded: datasets/Task09_Spleen.tar\n",
      "2024-07-16 16:53:18,952 - INFO - Verified 'Task09_Spleen.tar', md5: 410d4a301da4e5b2f6f86ec3ddba524e.\n",
      "2024-07-16 16:53:18,952 - INFO - Writing into directory: /home/chyang/Documents/monai_tutorials_gitee/monailabel/datasets.\n",
      "Task09_Spleen is downloaded at: datasets/Task09_Spleen\n"
     ]
    }
   ],
   "source": [
    "!monailabel datasets --download --name Task09_Spleen --output datasets"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1.4 Starting MONAI Label Server\n",
    "\n",
    "\"The `segmentation_spleen` model will be automatically downloaded upon starting the MONAI Label server. The network and checkpoint will be processed during the initialization steps of the `monailabel` command.\n",
    "\n",
    "**Note:** If you are running a MONAI Label server in this notebook and plan to close the notebook, ensure that you terminate the kernel first. Failing to do so might result in an issue where the port remains occupied from the previous session when you try to restart the server later. To prevent this, always terminate the kernel before closing the notebook."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Using PYTHONPATH=/home/chyang/anaconda3/envs:\n",
      "\n",
      "[2024-07-17 10:28:15,424] [576556] [MainThread] [INFO] (__main__:285) - USING:: version = False\n",
      "[2024-07-17 10:28:15,424] [576556] [MainThread] [INFO] (__main__:285) - USING:: app = /home/chyang/Documents/monai_tutorials_gitee/monailabel/apps/radiology\n",
      "[2024-07-17 10:28:15,424] [576556] [MainThread] [INFO] (__main__:285) - USING:: studies = /home/chyang/Documents/monai_tutorials_gitee/monailabel/datasets/Task09_Spleen/imagesTr\n",
      "[2024-07-17 10:28:15,424] [576556] [MainThread] [INFO] (__main__:285) - USING:: verbose = INFO\n",
      "[2024-07-17 10:28:15,425] [576556] [MainThread] [INFO] (__main__:285) - USING:: conf = [['models', 'segmentation_spleen']]\n",
      "[2024-07-17 10:28:15,425] [576556] [MainThread] [INFO] (__main__:285) - USING:: host = 0.0.0.0\n",
      "[2024-07-17 10:28:15,425] [576556] [MainThread] [INFO] (__main__:285) - USING:: port = 8000\n",
      "[2024-07-17 10:28:15,425] [576556] [MainThread] [INFO] (__main__:285) - USING:: uvicorn_app = monailabel.app:app\n",
      "[2024-07-17 10:28:15,425] [576556] [MainThread] [INFO] (__main__:285) - USING:: ssl_keyfile = None\n",
      "[2024-07-17 10:28:15,425] [576556] [MainThread] [INFO] (__main__:285) - USING:: ssl_certfile = None\n",
      "[2024-07-17 10:28:15,425] [576556] [MainThread] [INFO] (__main__:285) - USING:: ssl_keyfile_password = None\n",
      "[2024-07-17 10:28:15,425] [576556] [MainThread] [INFO] (__main__:285) - USING:: ssl_ca_certs = None\n",
      "[2024-07-17 10:28:15,425] [576556] [MainThread] [INFO] (__main__:285) - USING:: workers = None\n",
      "[2024-07-17 10:28:15,425] [576556] [MainThread] [INFO] (__main__:285) - USING:: limit_concurrency = None\n",
      "[2024-07-17 10:28:15,425] [576556] [MainThread] [INFO] (__main__:285) - USING:: access_log = False\n",
      "[2024-07-17 10:28:15,425] [576556] [MainThread] [INFO] (__main__:285) - USING:: root_path = \n",
      "[2024-07-17 10:28:15,425] [576556] [MainThread] [INFO] (__main__:285) - USING:: log_level = info\n",
      "[2024-07-17 10:28:15,425] [576556] [MainThread] [INFO] (__main__:285) - USING:: log_config = None\n",
      "[2024-07-17 10:28:15,425] [576556] [MainThread] [INFO] (__main__:285) - USING:: dryrun = False\n",
      "[2024-07-17 10:28:15,425] [576556] [MainThread] [INFO] (__main__:285) - USING:: action = start_server\n",
      "[2024-07-17 10:28:15,425] [576556] [MainThread] [INFO] (__main__:296) - \n",
      "Allow Origins: ['*']\n",
      "[2024-07-17 10:28:16,158] [576556] [MainThread] [INFO] (uvicorn.error:82) - Started server process [576556]\n",
      "[2024-07-17 10:28:16,158] [576556] [MainThread] [INFO] (uvicorn.error:48) - Waiting for application startup.\n",
      "App Init...\n",
      "[2024-07-17 10:28:16,158] [576556] [MainThread] [INFO] (monailabel.interfaces.utils.app:37) - Initializing App from: /home/chyang/Documents/monai_tutorials_gitee/monailabel/apps/radiology; studies: /home/chyang/Documents/monai_tutorials_gitee/monailabel/datasets/Task09_Spleen/imagesTr; conf: {'models': 'segmentation_spleen'}\n",
      "[2024-07-17 10:28:16,233] [576556] [MainThread] [INFO] (monailabel.utils.others.class_utils:57) - Subclass for MONAILabelApp Found: <class 'main.MyApp'>\n",
      "[2024-07-17 10:28:16,239] [576556] [MainThread] [INFO] (monailabel.utils.others.class_utils:57) - Subclass for TaskConfig Found: <class 'lib.configs.localization_vertebra.LocalizationVertebra'>\n",
      "[2024-07-17 10:28:16,239] [576556] [MainThread] [INFO] (monailabel.utils.others.class_utils:57) - Subclass for TaskConfig Found: <class 'lib.configs.localization_spine.LocalizationSpine'>\n",
      "[2024-07-17 10:28:16,240] [576556] [MainThread] [INFO] (monailabel.utils.others.class_utils:57) - Subclass for TaskConfig Found: <class 'lib.configs.segmentation_vertebra.SegmentationVertebra'>\n",
      "[2024-07-17 10:28:16,240] [576556] [MainThread] [INFO] (monailabel.utils.others.class_utils:57) - Subclass for TaskConfig Found: <class 'lib.configs.deepgrow_2d.Deepgrow2D'>\n",
      "[2024-07-17 10:28:16,246] [576556] [MainThread] [INFO] (monailabel.utils.others.class_utils:57) - Subclass for TaskConfig Found: <class 'lib.configs.deepedit.DeepEdit'>\n",
      "[2024-07-17 10:28:16,246] [576556] [MainThread] [INFO] (monailabel.utils.others.class_utils:57) - Subclass for TaskConfig Found: <class 'lib.configs.deepgrow_3d.Deepgrow3D'>\n",
      "[2024-07-17 10:28:16,247] [576556] [MainThread] [INFO] (monailabel.utils.others.class_utils:57) - Subclass for TaskConfig Found: <class 'lib.configs.segmentation.Segmentation'>\n",
      "[2024-07-17 10:28:16,247] [576556] [MainThread] [INFO] (monailabel.utils.others.class_utils:57) - Subclass for TaskConfig Found: <class 'lib.configs.segmentation_spleen.SegmentationSpleen'>\n",
      "[2024-07-17 10:28:16,247] [576556] [MainThread] [INFO] (main:95) - +++ Adding Model: segmentation_spleen => lib.configs.segmentation_spleen.SegmentationSpleen\n",
      "[2024-07-17 10:28:16,278] [576556] [MainThread] [INFO] (lib.configs.segmentation_spleen:79) - EPISTEMIC Enabled: False; Samples: 5\n",
      "[2024-07-17 10:28:16,278] [576556] [MainThread] [INFO] (main:98) - +++ Using Models: ['segmentation_spleen']\n",
      "[2024-07-17 10:28:16,278] [576556] [MainThread] [INFO] (monailabel.interfaces.app:135) - Init Datastore for: /home/chyang/Documents/monai_tutorials_gitee/monailabel/datasets/Task09_Spleen/imagesTr\n",
      "[2024-07-17 10:28:16,279] [576556] [MainThread] [INFO] (monailabel.datastore.local:130) - Auto Reload: True; Extensions: ['*.nii.gz', '*.nii', '*.nrrd', '*.jpg', '*.png', '*.tif', '*.svs', '*.xml']\n",
      "[2024-07-17 10:28:16,283] [576556] [MainThread] [INFO] (monailabel.datastore.local:577) - Invalidate count: 0\n",
      "[2024-07-17 10:28:16,283] [576556] [MainThread] [INFO] (monailabel.datastore.local:151) - Start observing external modifications on datastore (AUTO RELOAD)\n",
      "[2024-07-17 10:28:16,285] [576556] [MainThread] [INFO] (main:128) - +++ Adding Inferer:: segmentation_spleen => <lib.infers.segmentation_spleen.SegmentationSpleen object at 0x71a80a3d08e0>\n",
      "[2024-07-17 10:28:16,286] [576556] [MainThread] [INFO] (main:194) - {'segmentation_spleen': <lib.infers.segmentation_spleen.SegmentationSpleen object at 0x71a80a3d08e0>, 'Histogram+GraphCut': <monailabel.scribbles.infer.HistogramBasedGraphCut object at 0x71a80802b880>, 'GMM+GraphCut': <monailabel.scribbles.infer.GMMBasedGraphCut object at 0x71a80802ba60>}\n",
      "[2024-07-17 10:28:16,286] [576556] [MainThread] [INFO] (main:209) - +++ Adding Trainer:: segmentation_spleen => <lib.trainers.segmentation_spleen.SegmentationSpleen object at 0x71a80802b9a0>\n",
      "[2024-07-17 10:28:16,286] [576556] [MainThread] [INFO] (monailabel.utils.sessions:51) - Session Path: /home/chyang/.cache/monailabel/sessions\n",
      "[2024-07-17 10:28:16,286] [576556] [MainThread] [INFO] (monailabel.utils.sessions:52) - Session Expiry (max): 3600\n",
      "[2024-07-17 10:28:16,286] [576556] [MainThread] [INFO] (monailabel.interfaces.app:469) - App Init - completed\n",
      "[2024-07-17 10:28:16,286] [timeloop] [INFO] Starting Timeloop..\n",
      "[2024-07-17 10:28:16,286] [576556] [MainThread] [INFO] (timeloop:60) - Starting Timeloop..\n",
      "[2024-07-17 10:28:16,286] [timeloop] [INFO] Registered job <function MONAILabelApp.on_init_complete.<locals>.run_scheduler at 0x71a8087b38b0>\n",
      "[2024-07-17 10:28:16,286] [576556] [MainThread] [INFO] (timeloop:42) - Registered job <function MONAILabelApp.on_init_complete.<locals>.run_scheduler at 0x71a8087b38b0>\n",
      "[2024-07-17 10:28:16,286] [timeloop] [INFO] Timeloop now started. Jobs will run based on the interval set\n",
      "[2024-07-17 10:28:16,286] [576556] [MainThread] [INFO] (timeloop:63) - Timeloop now started. Jobs will run based on the interval set\n",
      "[2024-07-17 10:28:16,287] [576556] [MainThread] [INFO] (uvicorn.error:62) - Application startup complete.\n",
      "[2024-07-17 10:28:16,287] [576556] [MainThread] [INFO] (uvicorn.error:214) - Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)\n",
      "[2024-07-17 10:28:48,931] [576556] [MainThread] [INFO] (monailabel.endpoints.infer:171) - Infer Request: {'model': 'segmentation_spleen', 'image': 'spleen_47', 'device': 'NVIDIA GeForce RTX 3080 Ti', 'result_extension': '.nrrd', 'result_dtype': 'uint8', 'client_id': 'user-xyz'}\n",
      "[2024-07-17 10:28:48,932] [576556] [MainThread] [INFO] (monailabel.tasks.infer.basic_infer:280) - Infer Request (final): {'device': 'cuda', 'model': 'segmentation_spleen', 'image': '/home/chyang/Documents/monai_tutorials_gitee/monailabel/datasets/Task09_Spleen/imagesTr/spleen_47.nii.gz', 'result_extension': '.nrrd', 'result_dtype': 'uint8', 'client_id': 'user-xyz', 'description': 'A pre-trained model for volumetric (3D) segmentation of the spleen from CT image'}\n",
      "[2024-07-17 10:28:48,933] [576556] [MainThread] [INFO] (monailabel.interfaces.utils.transform:76) - PRE - Run Transform(s)\n",
      "[2024-07-17 10:28:48,934] [576556] [MainThread] [INFO] (monailabel.interfaces.utils.transform:77) - PRE - Input Keys: ['device', 'model', 'image', 'result_extension', 'result_dtype', 'client_id', 'description', 'image_path']\n",
      "[2024-07-17 10:28:49,480] [576556] [MainThread] [INFO] (monailabel.interfaces.utils.transform:122) - PRE - Transform (LoadImaged): Time: 0.5466; image: torch.Size([512, 512, 88])(torch.float32)\n",
      "[2024-07-17 10:28:49,628] [576556] [MainThread] [INFO] (monailabel.interfaces.utils.transform:122) - PRE - Transform (EnsureTyped): Time: 0.1476; image: torch.Size([512, 512, 88])(torch.float32)\n",
      "[2024-07-17 10:28:49,629] [576556] [MainThread] [INFO] (monailabel.interfaces.utils.transform:122) - PRE - Transform (EnsureChannelFirstd): Time: 0.0003; image: torch.Size([1, 512, 512, 88])(torch.float32)\n",
      "[2024-07-17 10:28:49,630] [576556] [MainThread] [INFO] (monailabel.interfaces.utils.transform:122) - PRE - Transform (Orientationd): Time: 0.0012; image: torch.Size([1, 512, 512, 88])(torch.float32)\n",
      "[2024-07-17 10:28:50,021] [576556] [MainThread] [ERROR] (uvicorn.error:412) - Exception in ASGI application\n",
      "Traceback (most recent call last):\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/uvicorn/protocols/http/h11_impl.py\", line 407, in run_asgi\n",
      "    result = await app(  # type: ignore[func-returns-value]\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/uvicorn/middleware/proxy_headers.py\", line 69, in __call__\n",
      "    return await self.app(scope, receive, send)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/fastapi/applications.py\", line 1054, in __call__\n",
      "    await super().__call__(scope, receive, send)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/applications.py\", line 123, in __call__\n",
      "    await self.middleware_stack(scope, receive, send)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/middleware/errors.py\", line 186, in __call__\n",
      "    raise exc\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/middleware/errors.py\", line 164, in __call__\n",
      "    await self.app(scope, receive, _send)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/middleware/cors.py\", line 85, in __call__\n",
      "    await self.app(scope, receive, send)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/middleware/exceptions.py\", line 65, in __call__\n",
      "    await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n",
      "    raise exc\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n",
      "    await app(scope, receive, sender)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/routing.py\", line 756, in __call__\n",
      "    await self.middleware_stack(scope, receive, send)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/routing.py\", line 776, in app\n",
      "    await route.handle(scope, receive, send)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/routing.py\", line 297, in handle\n",
      "    await self.app(scope, receive, send)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/routing.py\", line 77, in app\n",
      "    await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n",
      "    raise exc\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n",
      "    await app(scope, receive, sender)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/routing.py\", line 72, in app\n",
      "    response = await func(request)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/fastapi/routing.py\", line 278, in app\n",
      "    raw_response = await run_endpoint_function(\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/fastapi/routing.py\", line 191, in run_endpoint_function\n",
      "    return await dependant.call(**values)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/monailabel/endpoints/infer.py\", line 206, in api_run_inference\n",
      "    return run_inference(background_tasks, model, image, session_id, params, file, label, output)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/monailabel/endpoints/infer.py\", line 172, in run_inference\n",
      "    result = instance.infer(request)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/monailabel/interfaces/app.py\", line 307, in infer\n",
      "    result_file_name, result_json = task(request)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/monailabel/tasks/infer/basic_infer.py\", line 298, in __call__\n",
      "    data = self.run_pre_transforms(data, pre_transforms)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/monailabel/tasks/infer/basic_infer.py\", line 400, in run_pre_transforms\n",
      "    return run_transforms(data, transforms, log_prefix=\"PRE\", use_compose=False)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/monailabel/interfaces/utils/transform.py\", line 106, in run_transforms\n",
      "    data = t(data)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/monai/transforms/spatial/dictionary.py\", line 510, in __call__\n",
      "    d[key] = self.spacing_transform(\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/monai/transforms/spatial/array.py\", line 525, in __call__\n",
      "    data_array = self.sp_resample(\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/monai/transforms/spatial/array.py\", line 223, in __call__\n",
      "    return spatial_resample(\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/monai/transforms/spatial/functional.py\", line 178, in spatial_resample\n",
      "    img = affine_xform(img.unsqueeze(0), theta=xform.to(img), spatial_size=spatial_size).squeeze(0)  # type: ignore\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/torch/nn/modules/module.py\", line 1532, in _wrapped_call_impl\n",
      "    return self._call_impl(*args, **kwargs)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/torch/nn/modules/module.py\", line 1541, in _call_impl\n",
      "    return forward_call(*args, **kwargs)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/monai/networks/layers/spatial_transforms.py\", line 584, in forward\n",
      "    grid = nn.functional.affine_grid(theta=theta[:, :sr], size=list(dst_size), align_corners=self.align_corners)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/torch/nn/functional.py\", line 4445, in affine_grid\n",
      "    return torch.affine_grid_generator(theta, size, align_corners)\n",
      "torch.cuda.OutOfMemoryError: CUDA out of memory. Tried to allocate 1.58 GiB. GPU \n",
      "[2024-07-17 10:28:55,137] [576556] [MainThread] [INFO] (monailabel.endpoints.infer:171) - Infer Request: {'model': 'segmentation_spleen', 'image': 'spleen_47', 'device': 'NVIDIA GeForce RTX 3080 Ti', 'result_extension': '.nrrd', 'result_dtype': 'uint8', 'client_id': 'user-xyz'}\n",
      "[2024-07-17 10:28:55,137] [576556] [MainThread] [INFO] (monailabel.tasks.infer.basic_infer:280) - Infer Request (final): {'device': 'cuda', 'model': 'segmentation_spleen', 'image': '/home/chyang/Documents/monai_tutorials_gitee/monailabel/datasets/Task09_Spleen/imagesTr/spleen_47.nii.gz', 'result_extension': '.nrrd', 'result_dtype': 'uint8', 'client_id': 'user-xyz', 'description': 'A pre-trained model for volumetric (3D) segmentation of the spleen from CT image'}\n",
      "[2024-07-17 10:28:55,138] [576556] [MainThread] [INFO] (monailabel.interfaces.utils.transform:76) - PRE - Run Transform(s)\n",
      "[2024-07-17 10:28:55,138] [576556] [MainThread] [INFO] (monailabel.interfaces.utils.transform:77) - PRE - Input Keys: ['device', 'model', 'image', 'result_extension', 'result_dtype', 'client_id', 'description', 'image_path']\n",
      "[2024-07-17 10:28:55,682] [576556] [MainThread] [INFO] (monailabel.interfaces.utils.transform:122) - PRE - Transform (LoadImaged): Time: 0.5433; image: torch.Size([512, 512, 88])(torch.float32)\n",
      "[2024-07-17 10:28:55,691] [576556] [MainThread] [INFO] (monailabel.interfaces.utils.transform:122) - PRE - Transform (EnsureTyped): Time: 0.0091; image: torch.Size([512, 512, 88])(torch.float32)\n",
      "[2024-07-17 10:28:55,691] [576556] [MainThread] [INFO] (monailabel.interfaces.utils.transform:122) - PRE - Transform (EnsureChannelFirstd): Time: 0.0001; image: torch.Size([1, 512, 512, 88])(torch.float32)\n",
      "[2024-07-17 10:28:55,692] [576556] [MainThread] [INFO] (monailabel.interfaces.utils.transform:122) - PRE - Transform (Orientationd): Time: 0.0008; image: torch.Size([1, 512, 512, 88])(torch.float32)\n",
      "[2024-07-17 10:28:55,708] [576556] [MainThread] [ERROR] (uvicorn.error:412) - Exception in ASGI application\n",
      "Traceback (most recent call last):\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/uvicorn/protocols/http/h11_impl.py\", line 407, in run_asgi\n",
      "    result = await app(  # type: ignore[func-returns-value]\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/uvicorn/middleware/proxy_headers.py\", line 69, in __call__\n",
      "    return await self.app(scope, receive, send)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/fastapi/applications.py\", line 1054, in __call__\n",
      "    await super().__call__(scope, receive, send)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/applications.py\", line 123, in __call__\n",
      "    await self.middleware_stack(scope, receive, send)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/middleware/errors.py\", line 186, in __call__\n",
      "    raise exc\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/middleware/errors.py\", line 164, in __call__\n",
      "    await self.app(scope, receive, _send)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/middleware/cors.py\", line 85, in __call__\n",
      "    await self.app(scope, receive, send)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/middleware/exceptions.py\", line 65, in __call__\n",
      "    await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n",
      "    raise exc\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n",
      "    await app(scope, receive, sender)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/routing.py\", line 756, in __call__\n",
      "    await self.middleware_stack(scope, receive, send)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/routing.py\", line 776, in app\n",
      "    await route.handle(scope, receive, send)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/routing.py\", line 297, in handle\n",
      "    await self.app(scope, receive, send)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/routing.py\", line 77, in app\n",
      "    await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/_exception_handler.py\", line 64, in wrapped_app\n",
      "    raise exc\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n",
      "    await app(scope, receive, sender)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/starlette/routing.py\", line 72, in app\n",
      "    response = await func(request)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/fastapi/routing.py\", line 278, in app\n",
      "    raw_response = await run_endpoint_function(\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/fastapi/routing.py\", line 191, in run_endpoint_function\n",
      "    return await dependant.call(**values)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/monailabel/endpoints/infer.py\", line 206, in api_run_inference\n",
      "    return run_inference(background_tasks, model, image, session_id, params, file, label, output)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/monailabel/endpoints/infer.py\", line 172, in run_inference\n",
      "    result = instance.infer(request)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/monailabel/interfaces/app.py\", line 307, in infer\n",
      "    result_file_name, result_json = task(request)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/monailabel/tasks/infer/basic_infer.py\", line 298, in __call__\n",
      "    data = self.run_pre_transforms(data, pre_transforms)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/monailabel/tasks/infer/basic_infer.py\", line 400, in run_pre_transforms\n",
      "    return run_transforms(data, transforms, log_prefix=\"PRE\", use_compose=False)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/monailabel/interfaces/utils/transform.py\", line 106, in run_transforms\n",
      "    data = t(data)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/monai/transforms/spatial/dictionary.py\", line 510, in __call__\n",
      "    d[key] = self.spacing_transform(\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/monai/transforms/spatial/array.py\", line 525, in __call__\n",
      "    data_array = self.sp_resample(\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/monai/transforms/spatial/array.py\", line 223, in __call__\n",
      "    return spatial_resample(\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/monai/transforms/spatial/functional.py\", line 178, in spatial_resample\n",
      "    img = affine_xform(img.unsqueeze(0), theta=xform.to(img), spatial_size=spatial_size).squeeze(0)  # type: ignore\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/torch/nn/modules/module.py\", line 1532, in _wrapped_call_impl\n",
      "    return self._call_impl(*args, **kwargs)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/torch/nn/modules/module.py\", line 1541, in _call_impl\n",
      "    return forward_call(*args, **kwargs)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/monai/networks/layers/spatial_transforms.py\", line 584, in forward\n",
      "    grid = nn.functional.affine_grid(theta=theta[:, :sr], size=list(dst_size), align_corners=self.align_corners)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/torch/nn/functional.py\", line 4445, in affine_grid\n",
      "    return torch.affine_grid_generator(theta, size, align_corners)\n",
      "torch.cuda.OutOfMemoryError: CUDA out of memory. Tried to allocate 1.58 GiB. GPU \n",
      "^C\n",
      "[2024-07-17 10:29:16,955] [576556] [MainThread] [INFO] (uvicorn.error:258) - Shutting down\n",
      "[2024-07-17 10:29:17,055] [576556] [MainThread] [INFO] (uvicorn.error:67) - Waiting for application shutdown.\n",
      "App Shutdown...\n",
      "[2024-07-17 10:29:17,055] [576556] [MainThread] [INFO] (uvicorn.error:76) - Application shutdown complete.\n",
      "[2024-07-17 10:29:17,055] [576556] [MainThread] [INFO] (uvicorn.error:92) - Finished server process [576556]\n",
      "Traceback (most recent call last):\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/runpy.py\", line 197, in _run_module_as_main\n",
      "    return _run_code(code, main_globals, None,\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/runpy.py\", line 87, in _run_code\n",
      "    exec(code, run_globals)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/monailabel/main.py\", line 356, in <module>\n",
      "    Main().run()\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/monailabel/main.py\", line 135, in run\n",
      "    self.action_start_server(args)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/monailabel/main.py\", line 242, in action_start_server\n",
      "    uvicorn.run(\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/uvicorn/main.py\", line 575, in run\n",
      "    server.run()\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/uvicorn/server.py\", line 65, in run\n",
      "    return asyncio.run(self.serve(sockets=sockets))\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/asyncio/runners.py\", line 44, in run\n",
      "    return loop.run_until_complete(main)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/asyncio/base_events.py\", line 634, in run_until_complete\n",
      "    self.run_forever()\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/asyncio/base_events.py\", line 601, in run_forever\n",
      "    self._run_once()\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/asyncio/base_events.py\", line 1905, in _run_once\n",
      "    handle._run()\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/asyncio/events.py\", line 80, in _run\n",
      "    self._context.run(self._callback, *self._args)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/uvicorn/server.py\", line 69, in serve\n",
      "    await self._serve(sockets)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/contextlib.py\", line 126, in __exit__\n",
      "    next(self.gen)\n",
      "  File \"/home/chyang/anaconda3/envs/monai/lib/python3.9/site-packages/uvicorn/server.py\", line 328, in capture_signals\n",
      "    signal.raise_signal(captured_signal)\n",
      "KeyboardInterrupt\n"
     ]
    }
   ],
   "source": [
    "!monailabel start_server --app apps/radiology --studies datasets/Task09_Spleen/imagesTr --conf models segmentation_spleen"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. Auto Segmentation with 3D Slicer\n",
    "\n",
    "Below is a step-by-step tutorial on using 3D Slicer for auto spleen segmentation. Pre-trained model is provided and loaded by MONAI Label server.\n",
    "\n",
    "### Installation of 3D Slicer and MONAI Label Plugin\n",
    "\n",
    "You can download 3D Slicer on the [3D Slicer download page](https://download.slicer.org/).\n",
    "MONAI Label supports stable and preview versions of 3D Slicer: [Stable and Preview Version >= 5.0](https://download.slicer.org/).\n",
    "\n",
    "**For Ubuntu**\n",
    "\n",
    "**Prerequisites for 3D Slicer**: Slicer is expected to work on the vast majority of desktop and server Linux distributions. The system is required to provide at least GLIBC 2.17 and GLIBCCC 3.4.19. For more details, please refer to [prerequisites](https://slicer.readthedocs.io/en/latest/user_guide/getting_started.html#linux). \n",
    "\n",
    "As an example, Ubuntu users can click the downloaded 3D Slicer file and extract to the working folder, then click \"Slicer\" to open the 3D Slicer viewer. Specifically, Open the tar.gz archive and copy directory to the location of your choice. Installation of additional packages may be necessary depending on the Linux distribution and version. Run the Slicer executable to start the 3D Slicer.\n",
    "\n",
    "**For Windows**\n",
    "\n",
    "Download and run the 3D Slicer installer. Once installed, you can run `Slicer` from the Windows Start Menu.\n",
    "\n",
    "#### Install MONAI Label plugin from Slicer Extension Manager\n",
    "\n",
    "**Step 1:** Start 3D Slicer and navigate to **View** -> **Extension Manager** -> **Active Learning** -> **MONAI Label**\n",
    "\n",
    "<img src=\"./figures/monailabel_radiology_3dslicer/3dslicer-extensions-manager.png\" alt=\"drawing\" width=\"600\"/>\n",
    "\n",
    "**Step 2:** Install the MONAI Label plugin (click \"install\") and restart 3D Slicer. The \"Restart\" button is in the lower right-hand corner of the Extension Manager dialog box.\n",
    "\n",
    "**Step 3:** Add shortcut: Navigate to **Edit** -> **Application Settings**, under the **Modules** panel drag **MONAI Label** into the **Favorite Modules** panel. Click **OK**, restart 3D Slicer, and the MONAI Label icon <img src= \"./figures/monailabel_radiology_3dslicer/MONAILabel.png\" alt=\" drawing\" width=\" 20\"/> will be visible in the toolbar.\n",
    "\n",
    "<img src=\"./figures/monailabel_radiology_3dslicer/monai-label-plugin-favorite-modules-1.png\" alt=\"drawing\" width=\"600\"/>\n",
    "\n",
    "\n",
    "### 2.1 Start 3D Slicer and MONAI Label Plugin\n",
    "\n",
    "- On the menu bar navigate click MONAI Label, connect and Check MONAI Label Server Address/Name, radiology app, and confirm 3D Slicer is connected to MONAI Label server correctly, if no, fill in the correct server address and port.\n",
    "\n",
    "![slicer1](./figures/monailabel_radiology_3dslicer/slicer1.png)\n",
    "\n",
    "\n",
    "### 2.2 Select Model and Fetch Data\n",
    "\n",
    "- Select the model users would like to use, such as \"**segmentation_spleen**\" in this tutorial, click **next sample** to load image data from study datastore.\n",
    "\n",
    "![slicer1](./figures/monailabel_radiology_3dslicer/slicer2.png)\n",
    "\n",
    "\n",
    "### 2.3 Run Auto Segmentation\n",
    "\n",
    "- MONAI Label has provided pre-trained model weights for the spleen segmentation model, click **run** to do the inference on the currently loaded data. \n",
    "\n",
    "- Note: the pre-trained models will be downloaded when starting MONAI Label server in the \"**model**\" folder. For instance, in this use case, the downloaded pre-trained model is saved at \"**apps/radiology/model/pretrained_segmentation_spleen.pt**\".\n",
    "\n",
    "- Users may move the slices and location to view the automatic inferences segmentation.\n",
    "\n",
    "![slicer1](./figures/monailabel_radiology_3dslicer/slicer3.png)\n",
    "\n",
    "\n",
    "### 2.4 Edit Annotations and Submit Label\n",
    "\n",
    "- Users can edit the inference labels manually using Segment Editor, the tool for adjusting annotation. Once done annotation, click **Submit Label** to save the ground truth label to the file system.\n",
    "\n",
    "- Note: the final annotations will be saved to \"**labels/final**\" folder in the study dataset, for example, in this use case, the ground truth label will be saved to \"**datasets/Task09_Spleen/imagesTr/labels/final**\"\n",
    "\n",
    "#### AI assisted corrections:\n",
    "\n",
    "![scribbles](./figures/monailabel_radiology_3dslicer/scribbles.png)\n",
    "\n",
    "#### Corrections with Segment Editor:\n",
    "\n",
    "![slicer1](./figures/monailabel_radiology_3dslicer/slicer4.png)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. Active Learning with 3D Slicer\n",
    "\n",
    "Active learning and interactive fine-tuning models have highlighted features in MONAI Label, users can train their models anytime when new annotated labels are saved. Click **Train** button, MONAI Label server will fetch saved final ground truth label and fine-tune the prior model. \n",
    "\n",
    "![slicer1](./figures/monailabel_radiology_3dslicer/slicer5.png)\n",
    "\n",
    "Users can do auto segmentation using the latest fine-tuned model. \n",
    "Active learning process will select unlabeld batch data.\n",
    "\n",
    "Next image selected, the already trained images will be marked as labeled data, then won't be selected for next labeling batch. Active learning strategies such as \"first/random\" will be used for selecting which unlabeled data to fetch. \n",
    "\n",
    "For general active learning workflow design, see the slide: ![activeL](./figures/monailabel_radiology_3dslicer/activeLearning.png)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4. Repeat the Interactive Labeling Process \n",
    "\n",
    "Repeated fetch data and active learning process to section 2.2, until all unlabeled data are annotated and trained. \n",
    "\n",
    "For each training loop, the new best metric model will be saved in \"**model/<model_name>.pt**\", in this use case, \"\"**apps/radiology/model/segmentation_spleen.pt**\" is saved. For detailed training stats and step models, refer to \"**apps/radiology/model/segmentation_spleen/train_01**\", "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5. Conclusion\n",
    "\n",
    "This tutorial demonstrates basic usage of MONAI Label with radiology app, a spleen segmentation task is introduced. Active learning process, auto segmentation, segmentation editor, submit labels, and save models are included. \n",
    "We highlight the interactive learning process when labeling a dataset, our platform can achieve incremental improvements and understand medical data better for researchers and clinicians. \n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.19"
  },
  "vscode": {
   "interpreter": {
    "hash": "916dbcbb3f70747c44a77c7bcd40155683ae19c65e1c03b4aa3499c5328201f1"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
